/**
 * 模板类型参数的示例。
 */

// 模板的声明，而不是定义。
template<class T> T f1(int n);
template<class T> T f2(T   n);

// 自动类型推导，需要看到函数体。
auto f3(auto n) { return 0 + n; }

#include <iostream>
using namespace std;

int main() {
  // 到此只看到模板的声明，不知道模板的定义。
  // 生成函数调用的代码时，只需知道参数和返回值的类型，无需了解函数体。
  // 所以函数体中的语句无助于模板类型的推导。
  cout << f1<double>(1) << endl; // 正确：明确指定T=double。
  // cout << f1(2) << endl;      // 错误：无法推导出T的类型。
  cout << f2<double>(3) << endl; // 正确：明确指定T=double。参数3将隐式转为double类型，再传参。
  cout << f2(4) << endl;         // 正确：明确指定T=double。
  cout << f3(5) << endl;
}

// 到这里才有模板定义。
template<class T> T f1(int n) { T t = 0 + n; return t; }
template<class T> T f2(T   n) { T t = 0 + n; return t; }
